﻿using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

/// <summary>
/// Summary description for CustomGridViewPager
/// </summary>
public class CustomGridViewPager
{
    private const int DEFAULT_MAX_VISIBLE = 0;
    private const string DEFAULT_COUNTER_TEXT = "Out";
    private const string DEFAULT_TOTAL_TEXT = "Total";

    protected int maxVisiblePageNumbers;
    protected int maxRows;
    protected int maxPageRows;
    protected int currentPageIndex;
    protected string pageCounterText;
    protected string pageCounterTotalText;

    private int firstPageNumber;
    private int lastPageNumber;
    private int totalPages;

    public CustomGridViewPager(int MaxRows, int MaxPageRows)
	{
		// Default Constructor		
		maxVisiblePageNumbers = DEFAULT_MAX_VISIBLE;
        maxRows = MaxRows;
        maxPageRows = MaxPageRows;
        totalPages = (int)Math.Ceiling((decimal)maxRows / maxPageRows);
	    pageCounterText = DEFAULT_COUNTER_TEXT;
	    pageCounterTotalText = DEFAULT_TOTAL_TEXT;
	}

	public CustomGridViewPager(int MaxVisible, int MaxRows, int MaxPageRows, string CounterText, string TotalText)
	{
        // Default Constructor		
		maxVisiblePageNumbers = DEFAULT_MAX_VISIBLE;
        maxRows = MaxRows;
        maxPageRows = MaxPageRows;
        totalPages = (int)Math.Ceiling((decimal)maxRows / maxPageRows);
	    pageCounterText = DEFAULT_COUNTER_TEXT;
        pageCounterTotalText = DEFAULT_TOTAL_TEXT;
	}


    public int MaxVisiblePageNumbers
    {
        get { return maxVisiblePageNumbers; }
        set { maxVisiblePageNumbers = value; }
    }

    public int MaxRows
    {
        get { return maxRows; }
        set { maxRows = value; }
    }

    public int CurrentPageIndex
    {
        get { return currentPageIndex; }
        set { currentPageIndex = value; }
    }

    public int MaxPageRows
    {
        get { return maxPageRows; }
        set { maxPageRows = value; }
    }

    public string PageCounterText
    {
        get { return pageCounterText; }
        set { pageCounterText = value; }
    }
    
    public string PageCounterTotalText
    {
        get { return pageCounterTotalText; }
        set { pageCounterTotalText = value; }
    }

    public void CreateCustomPager(Control Container, int StartIndex)
    {
        // Create custom pager inside the container.
        // An html table is used to format the custom pager.

        // No data to display.
        if (MaxRows == 0) return;

        currentPageIndex = (int)Math.Ceiling((decimal)StartIndex / maxPageRows);
                
        HtmlTable pagerInnerTable = (HtmlTable)Container.FindControl("pagerInnerTable");
        if (pagerInnerTable != null)
        {
            // Remove the dynamically created cells before recreating them.
            pagerInnerTable.Rows[0].Cells.Clear();
            CreatePageCounter(pagerInnerTable);

            CalcFirstPageNumber();
            CalcLastPageNumber();

            // default dynamic cell position. 
            // (after the pageCount, the "First" and the "Previous" cells).            
            int insertCellPosition = 0;
            if (CurrentPageIndex != 0)
            {
                CreateFirstPrev(pagerInnerTable);
                insertCellPosition = 2;
            }
                
            CreatePageNumbers(pagerInnerTable, ref insertCellPosition);

            int lastCellPosition = pagerInnerTable.Rows[0].Cells.Count - 1;
            if (CurrentPageIndex != totalPages - 1)
            {
                // The last page is currently displayed.
                CreateNextLast(pagerInnerTable, insertCellPosition);
            }

            UpdatePageCounter(pagerInnerTable);

            HtmlTable pagerOuterTable = (HtmlTable)Container.FindControl("pagerOuterTable");
            if (pagerOuterTable != null)
            {
                // Remove the pageGroups cell if it exists.
                if (pagerOuterTable.Rows[0].Cells.Count > 1)
                    pagerOuterTable.Rows[0].Cells.RemoveAt(1);
                CreatePageGroups(pagerOuterTable);
            }
        }
    }

    public event CommandEventHandler PageNumberClick;
    public event EventHandler PageGroupChange;

    private void CreatePageCounter(HtmlTable pagerInnerTable)
    {
        // Create the page counter label.
        HtmlTableCell tableCell = new HtmlTableCell();
        tableCell.Attributes.Add("class", "pageCounter");
        Label lblPageCounter = new Label();
        lblPageCounter.ID = "lblPageCounter";
        tableCell.Controls.Add(lblPageCounter);
        pagerInnerTable.Rows[0].Cells.Insert(0, tableCell);
    }

    private void CreateFirstPrev(HtmlTable pagerInnerTable)
    {
        // Create the First and the Previous buttons.
        HtmlTableCell tableCell = new HtmlTableCell();
        tableCell.Attributes.Add("class", "pageFirstLast");
        HtmlImage img = new HtmlImage();
        img.Src = "~/Images/firstpage.gif";
        LinkButton lnk = new LinkButton();
        lnk.ID = "lnkFirstPage";
        lnk.CssClass = "pagerLink";
        lnk.Text = "First";
        lnk.CommandName = "Page";
        lnk.CommandArgument = "0";
        lnk.Command += new CommandEventHandler(PageNumberClick);
        tableCell.Controls.Add(img);
        tableCell.Controls.Add(new LiteralControl("&nbsp;"));
        tableCell.Controls.Add(lnk);
        pagerInnerTable.Rows[0].Cells.Insert(1, tableCell);

        tableCell = new HtmlTableCell();
        tableCell.Attributes.Add("class", "pagePrevNextNumber");
        ImageButton imgBtn = new ImageButton();
        imgBtn.ID = "imgPrevPage";
        imgBtn.ImageUrl = "~/Images/prevpage.gif";
        imgBtn.ImageAlign = ImageAlign.AbsMiddle;
        imgBtn.CommandName = "Page";
        imgBtn.CommandArgument = ((currentPageIndex - 1) * maxPageRows).ToString();
        imgBtn.Command += new CommandEventHandler(PageNumberClick);
        tableCell.Controls.Add(imgBtn);
        pagerInnerTable.Rows[0].Cells.Insert(2, tableCell);
    }

    private void CreateNextLast(HtmlTable pagerInnerTable, int insertCellPosition)
    {
        // Create the Next and Last buttons.
        HtmlTableCell tableCell = new HtmlTableCell();
        tableCell.Attributes.Add("class", "pagePrevNextNumber");
        ImageButton imgBtn = new ImageButton();
        imgBtn.ID = "imgNextPage";
        imgBtn.ImageUrl = "~/Images/nextpage.gif";
        imgBtn.ImageAlign = ImageAlign.AbsMiddle;
        imgBtn.CommandName = "Page";
        imgBtn.CommandArgument = ((currentPageIndex + 1) * maxPageRows).ToString();
        imgBtn.Command += new CommandEventHandler(PageNumberClick);
        tableCell.Controls.Add(imgBtn);
        pagerInnerTable.Rows[0].Cells.Insert(insertCellPosition, tableCell);

        tableCell = new HtmlTableCell();
        tableCell.Attributes.Add("class", "pageFirstLast");
        HtmlImage img = new HtmlImage();
        img.Src = "~/Images/lastpage.gif";
        LinkButton lnk = new LinkButton();
        lnk.ID = "lnkLastPage";
        lnk.CssClass = "pagerLink";
        lnk.Text = "Last";
        lnk.CommandName = "Page";
        lnk.CommandArgument = ((totalPages-1) * maxPageRows).ToString();
        lnk.Command += new CommandEventHandler(PageNumberClick);
        tableCell.Controls.Add(lnk);
        tableCell.Controls.Add(new LiteralControl("&nbsp;"));
        tableCell.Controls.Add(img);
        pagerInnerTable.Rows[0].Cells.Insert(insertCellPosition+1, tableCell);
    }

    private void CreatePageNumbers(HtmlTable pagerInnerTable, ref int insertCellPosition)
    {
        for (int i = firstPageNumber, pos = 1; i <= lastPageNumber; i++, pos++)
        {
            // Create a new table cell for every data page number.
            HtmlTableCell tableCell = new HtmlTableCell();
            if (CurrentPageIndex == i - 1)
                tableCell.Attributes.Add("class", "pageCurrentNumber");
            else
                tableCell.Attributes.Add("class", "pagePrevNextNumber");

            // Create a new LinkButton for every data page number.
            LinkButton lnkPage = new LinkButton();
            lnkPage.ID = "Page" + i.ToString();
            lnkPage.Text = i.ToString();
            lnkPage.CommandName = "Page";
            lnkPage.CommandArgument = ((i - 1) * maxPageRows).ToString();
            lnkPage.Command += new CommandEventHandler(PageNumberClick);
            lnkPage.CssClass = "pagerLink";

            // Place link inside the table cell; Add the cell to the table row.                
            tableCell.Controls.Add(lnkPage);
            pagerInnerTable.Rows[0].Cells.Insert(insertCellPosition + pos, tableCell);
        }
        insertCellPosition = pagerInnerTable.Rows[0].Cells.Count;
    }

    private void CalcFirstPageNumber()
    {
        // Calculate the first, visible page number of the pager.             
        firstPageNumber = 1;
        if (MaxVisiblePageNumbers == DEFAULT_MAX_VISIBLE)
            MaxVisiblePageNumbers = totalPages;
            
        if (totalPages > MaxVisiblePageNumbers)
        {
            // Seperate page numbers in groups if necessary.
            if ((CurrentPageIndex + 1) > maxVisiblePageNumbers)
            {
                // Calculate the group to display.
                // Example: 
                //      totalPages = 12
                //      maxVisiblePageNumbers = 4
                //      CurrentPageIndex+1 = 7
                //      --> pageGroup = 2       (Page numbers: 5, 6, 7, 8)
                decimal pageGroup = Math.Ceiling((decimal)(CurrentPageIndex + 1) / MaxVisiblePageNumbers);
                // Calculate the first page number for the group to display.
                // Example :
                //      if pageGroup = 1 (Page numbers: 1,2,3,4) --> firstPageNumber = 1
                //      if pageGroup = 2 (Page numbers: 5,6,7,8) --> firstPageNumber = 5
                //      if pageGroup = 3 (Page numbers: 9,10,11,12) --> firstPageNumber = 9                        
                firstPageNumber = (int)(1 + (MaxVisiblePageNumbers * (pageGroup - 1)));
            }
        }
    }

    private void CalcLastPageNumber()
    {
        // Calculate the last, visible page number of the pager.
        lastPageNumber = totalPages;
        if (MaxVisiblePageNumbers == DEFAULT_MAX_VISIBLE)
            MaxVisiblePageNumbers = totalPages;
                    
        if (totalPages > MaxVisiblePageNumbers)
        {
            lastPageNumber = firstPageNumber + (MaxVisiblePageNumbers - 1);
            if (totalPages < lastPageNumber)
                lastPageNumber = totalPages;
        }
    }

    private void UpdatePageCounter(HtmlTable pagerInnerTable)
    {
        // Display current page number and total number of pages.        
        Label pageCounter = (Label)pagerInnerTable.Rows[0].Cells[0].FindControl("lblPageCounter");
        pageCounter.Text = "&nbsp;" + PageCounterText + "&nbsp;" + (currentPageIndex + 1).ToString() + "&nbsp;" + PageCounterTotalText + "&nbsp;" + totalPages.ToString() + "&nbsp";
    }

    private void CreatePageGroups(HtmlTable pagerOuterTable)
    {
        // Display page groups in pager if totalPages is greater than the maxVisiblePageNumbers.        

        // No data to display.
        if (MaxRows == 0) return;
        
        if (MaxVisiblePageNumbers == DEFAULT_MAX_VISIBLE)
            MaxVisiblePageNumbers = totalPages;
        
        int maxPageGroups = (int)Math.Ceiling((decimal)totalPages / MaxVisiblePageNumbers);
        if (totalPages > MaxVisiblePageNumbers)
        {
            int lastCellPosition = pagerOuterTable.Rows[0].Cells.Count - 1;
            decimal pageGroup = Math.Ceiling((decimal)(CurrentPageIndex + 1) / MaxVisiblePageNumbers);

            HtmlTableCell tableCell = new HtmlTableCell();
            tableCell.Attributes.Add("class", "pageGroups");
            
            DropDownList ddlPageGroups = new DropDownList();
            ddlPageGroups.ID = "ddlPageGroups";
            ddlPageGroups.AutoPostBack = true;
            ddlPageGroups.SelectedIndexChanged += new EventHandler(PageGroupChange);
            for (int pg = 1; pg <= maxPageGroups; pg++)
            {
                int groupFirstPageNumber = (int)(1 + (maxVisiblePageNumbers * (pg - 1)));
                int groupLastPageNumber = groupFirstPageNumber + (maxVisiblePageNumbers - 1);
                if (totalPages < groupLastPageNumber)
                    groupLastPageNumber = totalPages;
                string group = String.Format("{0} ... {1}", groupFirstPageNumber.ToString(), groupLastPageNumber.ToString());
                ListItem groupItem = new ListItem(group, (groupFirstPageNumber * maxPageRows).ToString());
                if (pageGroup == pg)
                    groupItem.Selected = true;
                ddlPageGroups.Items.Add(groupItem);
            }
            tableCell.Controls.Add(new LiteralControl("Pages:&nbsp;"));
            tableCell.Controls.Add(ddlPageGroups);
            pagerOuterTable.Rows[0].Cells.Insert(1, tableCell);
        }
    }
}